home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Diamond Collection
/
The Diamond Collection (Software Vault)(Digital Impact).ISO
/
cdr48
/
386p_200.zip
/
386MENU.ASM
< prev
next >
Wrap
Assembly Source File
|
1995-01-14
|
29KB
|
1,060 lines
.386p
code32 segment para public use32
assume cs:code32,ds:code32
include 386power.inc
include chario.inc
include 386video.inc
include 386keyb.inc
include pix.inc
; include common menu definitions
include 386mnu.inc
INPUT_ON macro
mov edi,_CHRMENU2
mov _CHRFNT,edi
endm
INPUT_OFF macro
mov edi,_CHRMENU1
mov _CHRFNT,edi
endm
E_NAME =4
E_VALUE =8
E_FN =12
E_MIN =16
E_MAX =20
E_STEP =24
; Header: text menu title
;
; db M_HEADER,t_col,maxwidth,touchngo
; dd text_p,x,y
;
; x,y = initial position IN PIXELS of the upper left border
; of this menu, or -1,-1 if the menu manager can freely choose
; where popup these.
; N.B. if x,y are out of range or the menu manager supports
; popup menu repositioning, these values will be
; modified by the menu manager.
; t_col = column position of entry name
; text_p = code32 offset to asciiz string to show starting from
; t_col column.
; maxwidth = maximum menu width in characters
; touchngo: 0=only ESC or an "exit" entry will end this menu
; 1=AFTER the first SELECTION, end this menu
; (useful for the "save game" or "load game" menu)
EB_T_COL =1
EB_MAXW =2
EB_TNG =3
sho_name:
mov edx,[ecx*4+ENTRY_ROW]
mov eax,_VDispX
mov esi,[ecx*4+ENTRY_DATA]
mov edi,_ScrBase
movzx ebp,byte ptr [esi+EB_T_COL]
add edx,_VDispY
mov ebx,[esi+E_NAME]
lea eax,[eax+ebp*8+16]
call _PutString
ret
name_show:
;ecx = current entry index
pushad
call sho_name
popad
ret
; Bar: text <-]#############[+> a "volume level" bar
;
; db M_BAR,t_col,in_col,in_len
; dd text_p, value_p, func_p,min, max, step
;
; in_col = colum position of the "volume level bar"
; starting with the <-] character
; in_len = lenght of the "volume bar" (excluding the <-] and [+> characters)
; value_p = code32 offset to the variable containing the value to show/set
; min = minimum allowed value
; max = maximum allowed value
; func_p = code32 offset of function to call every time the entry value
; is altered (use this for value checking/correction
; or to trigger special actions depending on the value )
; Function parameters:
; in:
; Segment registers pointing to the usual 386P segments.
; EAX = value "requested by user"
; to set into the variable pointed by value_p
; out:
; EAX = ALLOWED value to store into the variable
; (the menu manager will store it properly)
; IF CARRY SET, REFRESH ALL THE DISPLAYED DATA
; All other registers preserved.
;
; step = increment/decrement step for the variable pointed by value_p
;
udec: ; bar and unsigned integers
bdec:
; ecx = current entry index
mov esi,[ecx*4+ENTRY_DATA]
mov ebx,[esi+E_VALUE]
mov eax,[ebx]
mov edx,[esi+E_MIN]
mov ebp,[esi+E_STEP]
sub eax,edx
jnb gb_min
cut_down:
mov eax,edx
jmp short gb_checked
gb_min:
sub eax,ebp
jb cut_down
add eax,edx
jmp short gb_checked
uinc: ; bar and unsigned integers
binc:
; ecx = current entry index
mov esi,[ecx*4+ENTRY_DATA]
mov ebx,[esi+E_VALUE]
mov edx,[esi+E_MAX]
mov ebp,[esi+E_STEP]
mov eax,[ebx]
add eax,ebp
sub eax,edx
jb gb_max
xor eax,eax
gb_max:
add eax,edx
gb_checked:
xor edx,edx
call [esi+E_FN]
mov dl,[esi] ; menu type
mov [ebx],eax
jnc gb_rfr
mov eax,ENTRY_DATA
call m_refresh
gb_rfr:
jmp dword ptr [edx*4+SHOW] ;chain-call
EB_IN_COL =2
EB_IN_LEN =3
bstring db 40 dup(0)
bshow:
;ecx = current entry index
push ecx
call sho_name
mov edx,[esi+E_VALUE]
xor ebx,ebx
mov eax,[edx]
mov ebp,[esi+E_MIN]
mov bl,[esi+EB_IN_LEN]
mov edi,[esi+E_MAX]
cmp eax,edi
jbe low_enough
mov [edx],edi
mov eax,edi
low_enough:
shl ebx,3 ; multiply by 8 to get pixel lenght
sub eax,ebp
jnbe high_enough
mov [edx],ebp ; round to minimum
mov eax,ebp ;
high_enough:
sub edi,ebp
mul ebx
div edi
; eax=bar level in pixels
; ebx=bar maximum bar level in pixels
mov edi,offset bstring
shr ebx,3 ; back to "characters"
mov edx,eax
mov byte ptr [edi],ARROW_MINUS
lupp:
inc edi
sub eax,8
jbe outlevel
mov byte ptr [edi],BAR8
dec ebx
jmp short lupp
outlevel:
add eax,8
jne goodbar
mov al,BAR0 ; we have to avoid NULs
goodbar:
mov [edi],al
empbar:
inc edi
dec ebx
je outbarr
mov byte ptr [edi],BAR0
jmp short empbar
outbarr:
mov edx,[ecx*4+ENTRY_ROW]
mov word ptr [edi],ARROW_PLUS ; fancy trick, the high byte is NUL
mov ebx, offset bstring
mov eax,_VDispX
add edx,_VDispY
movzx ebp,byte ptr [esi+EB_IN_COL]
mov edi,_ScrBase
lea eax,[eax+ebp*8+16]
call _PutString
pop ecx
ret
; Int: text <-]_____________[+> a 32bit integer value
;
; db M_INT,t_col,in_col,idigits
; dd text_p, value_p, func_p, min, max, step
;
; idigits = maximum number of digits including optional sign character
EB_IDIGITS=3
isel:
xor eax,eax
mov edx,[ecx*4+ENTRY_ROW]
mov esi,[ecx*4+ENTRY_DATA]
push ecx
add edx,_VDispY
xor ecx,ecx
mov al,[esi+EB_IN_COL]
mov ebx,[esi+E_VALUE]
shl eax,3 ; multiply by 8
mov cl,[esi+EB_IDIGITS]
push ebx
INPUT_ON
add eax,_VDispX
mov ebx,[ebx]
mov edi,_ScrBase
add eax,16
call _GetInt
mov eax,ebx ; copy returned value
INPUT_OFF
pop ebx
pop ecx
jmp icheck
idec:
; ecx = current entry index
mov esi,[ecx*4+ENTRY_DATA]
mov ebx,[esi+E_VALUE]
mov eax,[ebx]
sub eax,[esi+E_STEP]
jmp short icheck
iinc:
; ecx = current entry index
mov esi,[ecx*4+ENTRY_DATA]
mov ebx,[esi+E_VALUE]
mov eax,[ebx]
add eax,[esi+E_STEP]
icheck:
cmp eax,[esi+E_MIN]
jnl gi_min
mov eax,[esi+E_MIN]
gi_min:
cmp eax,[esi+E_MAX]
jle gi_max
mov eax,[esi+E_MAX]
gi_max:
call [esi+E_FN]
mov [ebx],eax
jnc gi_rfr
mov eax,ENTRY_DATA
call m_refresh
gi_rfr:
; chain-call to ishow
ushow:
ishow:
;ecx = current entry index
push ecx
call sho_name
xor ebx,ebx
mov edx,[ecx*4+ENTRY_ROW]
xor ecx,ecx
mov bx,[esi+EB_IN_COL]
INPUT_ON
mov eax,_VDispX
xchg cl,bh ; cl = EB_IDIGITS
add edx,_VDispY
mov ebp,[esi+E_VALUE]
lea eax,[eax+ebx*8+16]
mov edi,_ScrBase
mov ebx,ds:[ebp]
cmp byte ptr [esi],M_INT
jne is_unsigned
call _PutInt
INPUT_OFF
pop ecx
ret
is_unsigned:
call _PutUnsigned
INPUT_OFF
pop ecx
ret
;
; Unsigned: text <-]_____________[+> a 32bit dword value
;
; db M_UNSIGNED,t_col,in_col,udigits
; dd text_p, value_p, func_p, min, max, step
;
; udigits = maximum number of digits (and no sign)
; ushow is included with ishow
; uinc and udec are the same as bdec and dinc
usel:
xor eax,eax
mov edx,[ecx*4+ENTRY_ROW]
mov esi,[ecx*4+ENTRY_DATA]
push ecx
add edx,_VDispY
xor ecx,ecx
INPUT_ON
mov al,[esi+EB_IN_COL]
mov ebx,[esi+E_VALUE]
shl eax,3 ; multiply by 8
mov cl,[esi+EB_IDIGITS]
add eax,_VDispX
mov ebx,[ebx]
mov edi,_ScrBase
add eax,16
call _GetUnsigned
mov eax,ebx ; copy returned value
INPUT_OFF
pop ecx
mov ebx,[esi+E_VALUE]
mov edx,[esi+E_MIN]
mov ebp,[esi+E_MAX]
cmp eax,edx
jnb gb_mgo
mov eax,edx
gb_mgo:
cmp eax,ebp
jb gb_go
mov eax,ebp
gb_go:
jmp gb_checked
;
; Pick_list: text <-]_____________[+> choose from a list
;
; db M_PICK,t_col,in_col,max_item_len
; dd text_p, value_p, func_p,picklist_p, picktop
;
; max_item_len = maximum lenght in characters of the strings
; pointed by the "pick list" table
; EVERY string into the pick-list must have this lenght
; (with "padding" spaces if the text is shorter
; and excluding the final NUL from the count).
;
; value_p = pointer to a dword with values ranging
; from 0 (for the first picklist string)
; to picktop-1 (for the last picklist string).
; picklist_p = pointer to an array of pointers (all code32 offsets)
; to strings describing the "values" you can choose]
E_PICKLIST = 16
E_PICKTOP = 20
pdec:
; ecx = current entry index
mov esi,[ecx*4+ENTRY_DATA]
mov ebx,[esi+E_VALUE]
mov eax,[ebx]
or eax,eax
jz pick_good
dec eax
jmp short pcheck
pinc:
; ecx = current entry index
mov esi,[ecx*4+ENTRY_DATA]
mov ebx,[esi+E_VALUE]
mov eax,[ebx]
inc eax
pcheck:
cmp eax,[esi+E_PICKTOP]
jb pick_good
mov eax,[esi+E_PICKTOP]
dec eax
pick_good:
call [esi+E_FN]
mov [ebx],eax
jnc pick_rfr
mov eax,ENTRY_DATA
call m_refresh
pick_rfr:
; chain call to pshow
pshow:
;ecx = current entry index
push ecx
call sho_name
mov ebx,[esi+E_VALUE]
mov edx,[ecx*4+ENTRY_ROW]
movzx ebp,byte ptr [esi+EB_IN_COL]
INPUT_ON
mov eax,_VDispX
add edx,_VDispY
mov ebx,[ebx]
mov esi,[esi+E_PICKLIST]
mov edi,_ScrBase
lea eax,[eax+ebp*8+16]
mov ebx,[esi+ebx*4] ; load pointer to string to display
call _PutString
INPUT_OFF
pop ecx
ret
; String: text _____________ string entry
;
; db M_STRING,t_col,in_col,max_string_characters
; dd text_p, value_p, sfunc_p
;
; function to call to check string, it is like func_p
; but eax is a POINTER to the actual string data
; and you cannot modify it!!!!!!!
ssel:
mov edx,[ecx*4+ENTRY_ROW]
mov esi,[ecx*4+ENTRY_DATA]
push ecx
INPUT_ON
mov eax,_VDispX
xor ecx,ecx
add edx,_VDispY
movzx ebp,byte ptr[esi+EB_IN_COL]
mov ebx,[esi+E_VALUE]
mov cl,[esi+EB_IDIGITS]
mov edi,_ScrBase
lea eax,[eax+ebp*8+16]
call _GetString
INPUT_OFF
pop ecx
mov eax,[esi+E_VALUE]
call [esi+E_FN]
jnc str_rfr
mov eax,ENTRY_DATA
call m_refresh
str_rfr:
; show it
sshow:
;ecx = current entry index
push ecx
; first of all, execute a row refresh
mov esi,DARK6_TEXT+(DARK6_TEXT shl 8)+(DARK6_TEXT shl 16)+(DARK6_TEXT shl 24)
mov eax,_VDispX
mov ebx,8
mov edx,_VDispY
add eax,16 ; skip the cursor columns
push ecx
add edx,[ecx*4+ENTRY_ROW]
mov edi,_ScrBase
mov ecx,38*2
call _Block ; set background
pop ecx
; menu name
call sho_name
; string value
INPUT_ON
mov edx,[ecx*4+ENTRY_ROW]
movzx ebp,byte ptr [esi+EB_IN_COL]
mov eax,_VDispX
add edx,_VDispY
mov ebx,[esi+E_VALUE]
lea eax,[eax+ebp*8+16]
mov edi,_ScrBase
call _PutString
INPUT_OFF
pop ecx
ret
; Submenu: text call a submenu
;
; db M_MENU,t_col,thru,m_disable
; dd text_p, menu_p
;
; menu_p = code32 offset of M_HEADER entry of menu to call
; when this entry is clicked.
; thru : 0 = when returning, reactivate this menu and refresh screen
; 1 = when returning, quit this menu automatically.
; m_disable: 0 = submenu can be selected
; 1 = this submenu cannot be activated
EB_THRU =2
EB_DISABLE =3
msel:
mov eax,ENTRY_DATA ; get header address
mov esi,[ecx*4+ENTRY_DATA]
push eax
push ecx
cmp byte ptr [esi+EB_DISABLE],0
jne old_menu
mov eax,[esi+E_VALUE]
call _PopMenu
cmp byte ptr [esi+EB_THRU],0
je old_menu
pop ecx
pop eax
pop ebx ; discard return address
; menu termination
popad
pop _CHRFNT
ret
old_menu:
pop ecx
pop eax
pushad
call m_refresh
popad
ret
; Call: text call a subroutine
;
; db M_CALL,t_col,thru,0
; dd text_p, procedure_p
;
; procedure_p = code32 offset of code to call
; when this entry is clicked.
; The function assumes cs=_SelCode, ds=es=ss=fs=_SelData
; gs=_SelZero, like the _PopMenu procedure.
; The called procedure must preserve all registers.
;
csel:
mov eax,ENTRY_DATA ; get header address
mov esi,[ecx*4+ENTRY_DATA]
push _CHRFNT
push eax
call dword ptr [esi+E_VALUE]
cmp byte ptr [esi+EB_THRU],0
je old_call
pop eax
pop _CHRFNT
pop ebx ; discard return address
; menu termination
popad
pop _CHRFNT
ret
old_call:
pop eax
pop _CHRFNT
call m_refresh
ret
; Toggle: [] text boolean entry
;
; db M_TOGGLE,t_col,flag_col,0
; dd text_p, bool_p, func_p
;
; flag_col = column position of '[]' on/off character
; bool_p = pointer to BYTE that can be toggled to 0 or to 1
; when clicking on this entry.
;
align byte
TOGGLES db FLAG_OFF,0,FLAG_ON,0
togg:
; ecx = current entry index
mov esi,[ecx*4+ENTRY_DATA]
mov ebx,[esi+E_VALUE]
mov al,[ebx]
inc al
tcheck:
and al,1
call [esi+E_FN]
mov [ebx],al
jnc tg_rfr
mov eax,ENTRY_DATA
call m_refresh
tg_rfr:
; chain call to tshow
tshow:
;ecx = current entry index
push ecx
; menu name
call sho_name
; toggle value
mov edx,[ecx*4+ENTRY_ROW]
xor ebx,ebx
mov edi,[esi+E_VALUE]
movzx ebp,byte ptr [esi+EB_IN_COL]
mov eax,_VDispX
mov bl,[edi]
add edx,_VDispY
lea eax,[eax+ebp*8+16]
lea ebx,[ebx*2+TOGGLES]
mov edi,_ScrBase
call _PutString
pop ecx
ret
; Key: text keytext keyboard key value
;
; db M_KEY,t_col,key_col,0
; dd text_p, key_p, func_p
;
; key_col = column position of TEXT (obtained from _KeyNames)
; describing the key.
; key_p = pointer to BYTE that contains key code
;
ksel: mov esi,[ecx*4+ENTRY_DATA]
mov edx,[ecx*4+ENTRY_ROW]
mov ebx,[esi+E_VALUE]
mov ebp,[esi+E_FN]
mov byte ptr [ebx],0
push eax ; dummy push
ooh_retry:
pop eax ; discard flags if retried
call kshowinput
call entry_refresh
pushad
call _ScanKeyb
mov edi,eax ; clear keyboard table
mov ecx,32 ;
xor eax,eax ;
rep stosd ;
popad
wait_release:
call _ScanKeyb
mov ebx,eax ;key table pointer
mov eax,1 ;key index (0 is NUL, so skip it)
kscanning:
cmp byte ptr [ebx+eax],KPRESSED
jne nkukkato
push ecx
mov byte ptr [ebx+eax],0
mov ecx,_KeyNames
mov ecx,[ecx+eax*4]
cmp ecx,_NotAKey
pop ecx
jne kukkato ; it is a known key
nkukkato:
inc eax ; increase index
cmp eax,128
jb kscanning
jmp short wait_release
kukkato:
call ebp
pushfd ;save flags
or eax,eax
jz ooh_retry ; a NUL entry is not allowed
mov ebx,[esi+E_VALUE]
mov [ebx],al
popfd
; chain call to kshow
jnc ky_rfr
mov eax,ENTRY_DATA
call m_refresh
ky_rfr:
kshow:
;ecx = current entry index
pushad
; first of all, execute a row refresh
mov esi,DARK6_TEXT+(DARK6_TEXT shl 8)+(DARK6_TEXT shl 16)+(DARK6_TEXT shl 24)
mov eax,_VDispX
mov ebx,8
mov edx,_VDispY
add eax,16 ; skip the cursor columns
push ecx
add edx,[ecx*4+ENTRY_ROW]
mov edi,_ScrBase
mov ecx,38*2
call _Block ; set background
pop ecx
; menu name
call sho_name
; key's value
INPUT_ON
mov esi,[ecx*4+ENTRY_DATA]
mov ebx,[esi+E_VALUE]
movzx ebp,byte ptr [esi+EB_IN_COL]
mov eax,_VDispX
mov edx,_VDispY
movzx ebx,byte ptr [ebx]
mov edi,_ScrBase
lea eax,[eax+ebp*8+16]
shl ebx,2
add edx,[ecx*4+ENTRY_ROW]
add ebx,_KeyNames
mov ebx,[ebx]
call _PutString
INPUT_OFF
popad
ret
pressakey db 'press a key',0
kshowinput: ; "show key entry" for input
;ecx = current entry index
pushad
; first of all, execute a row refresh
mov esi,DARK6_TEXT+(DARK6_TEXT shl 8)+(DARK6_TEXT shl 16)+(DARK6_TEXT shl 24)
mov eax,_VDispX
mov ebx,8
mov edx,_VDispY
add eax,16 ; skip the cursor columns
push ecx
add edx,[ecx*4+ENTRY_ROW]
mov edi,_ScrBase
mov ecx,38*2
call _Block ; set background
pop ecx
; menu name
call sho_name
; "press a key"
INPUT_ON
mov esi,[ecx*4+ENTRY_DATA]
movzx ebp,byte ptr [esi+EB_IN_COL]
mov eax,_VDispX
mov edx,_VDispY
mov edi,_ScrBase
lea eax,[eax+ebp*8+16]
add edx,[ecx*4+ENTRY_ROW]
mov ebx,offset pressakey
call _PutString
INPUT_OFF
popad
ret
; Exit: text "exit from this menu"
;
; db M_EXIT,t_col,0,0
; dd exit_text_p
;
; exit_text_p = pointer to the entry name
; (for example: 'CONTINUE GAME',0)
;
xsel:
pop eax ; discard return address
popad
pop _CHRFNT
ret
; End: etext end menu marker
; etext with optional text
; ....
; etext
;
;
; db M_END,t_col,t_lines,0
; dd etext_p
;
; t_lines = lines of text/string count of strings pointed by etext_p
;
; etext_p = pointer to a table of pointers to asciiz text strings
; to show on the bottom of the menu
; if ( etext_p == 0 ) then no text
; For example:
; if etext_p contains offset menu_usage
; and t_lines contains 4
; and there is:
;
; menu_usage dd e0,e1,e2,e3,e4,e5
;
; e0 db ' HOW',0
; e1 db ' MANY',0
; e2 db ' LINES',0
; e3 db 'YOU',0
; e4 db 'WILL',0
; e5 db ' SEE?',0
;
; You will see on the bottom of the menu:
; HOW
; MANY
; LINES
; YOU
;
; (the other strings are not displayed)
EB_T_LINES =2
eshow: push ecx
mov edx,[ecx*4+ENTRY_ROW]
mov eax,_VDispX
mov esi,[ecx*4+ENTRY_DATA]
mov edi,_ScrBase
movzx ebx,byte ptr [esi+EB_T_COL]
add edx,_VDispY
movzx ebp,byte ptr [esi+EB_T_LINES]
lea eax,[eax+ebx*8+16]
mov esi,[esi+E_NAME]
nxstring:
mov ebx,[esi]
add esi,4
call _PutString
add edx,8
dec ebp
jnz nxstring
pop ecx
ret
none:
ret
no_more_cursor db ' ',0
uup:
cmp ecx,1
jbe noo_id
mov ebp,-1
jmp short pulisci
dnn:
cmp ecx,ENTRIES
jnb noo_id
mov ebp,+1
pulisci:
push ecx
mov eax,0
mov edx,[ecx*4+ENTRY_ROW]
mov ebx,8
mov ecx,4
mov edi,_ScrBase
call _TouchBlock
mov eax,_VDispX
mov ebx,offset no_more_cursor
add edx,_VDispY
mov edi,_ScrBase
call _PutString
pop ecx
add ecx,ebp
noo_id: ret
align byte
; M_HEADER M_BAR M_INT M_UNSIGNED M_PICK M_STRING M_MENU M_CALL M_TOGGLE M_KEY M_EXIT M_END
ENTRY_SIZE db 4*4, 7*4, 7*4, 7*4, 6*4, 4*4, 3*4, 3*4, 4*4, 4*4, 2*4, 2*4
align dword
INCREMENT dd none, binc, iinc, uinc, pinc, none, none, none, togg, none, none, none
DECREMENT dd none, bdec, idec, udec, pdec, none, none, none, togg, none, none, none
SELECT dd none, none, isel, usel, none, ssel, msel, csel, none, ksel, xsel, none
UPP dd none, uup, uup, uup, uup, uup, uup, uup, uup, uup, uup, none
DDN dd none, dnn, dnn, dnn, dnn, dnn, dnn, dnn, dnn, dnn, dnn, none
SHOW dd name_show,bshow,ishow,ushow, pshow, sshow, name_show,name_show,tshow, kshow, name_show, eshow
ENTRY_DATA dd 25 dup(0)
ENTRY_ROW dd 25 dup(0)
ENTRIES dd 0 ; "active" entries (excluding m_header and m_end)
align byte
; empty string to clean screen
zapper db ' ',0
tfe db '386MENU: Too few menu entries, need at least a menu exit option',CR,LF,'$'
too_few_entries:
mov _386Return,offset tfe
jmp _Exit
tmm db '386MENU: Too many menu entries',CR,LF,'$'
too_many_entries:
mov _386Return,offset tmm
jmp _Exit
touchngo db 0
m_refresh: ; refresh menu data structures and screen image
; eax= ptr to menu description
pushad
mov dl,byte ptr [eax+EB_TNG]
xor ebp,ebp
xor ebx,ebx
mov touchngo,dl
mov edi,offset ENTRY_DATA
xor edx,edx
again:
mov bl,[eax]
stosd ; data entry position
mov dl,[ebx+ENTRY_SIZE]
inc ebp
add eax,edx
cmp bl,M_END
jne again
cmp ebp,23 ; 25 lines - 2 interlines == 23 entries max.
ja too_many_entries
sub eax,edx ; back to last entry
xor edx,edx
sub ebp,2 ; "valid entries" count
jbe too_few_entries
mov ebx,22 ; 25 - 1_title_row - 2_interlines
mov dl,[eax+EB_T_LINES] ; get lines of ending text
sub ebx,edx ; available_entries - bottom_menu_text
shl edx,3 ; pixel-lines of text
push edx ;save lines of text in the end
; now calculate menu row positions
shl ebx,3 ; get value in pixels
mov ENTRIES,ebp ; save "valid entries" count
xor edx,edx
mov eax,ebx ; divide available lines by entries
div ebp ;
cmp eax,8
jb too_many_entries ; less than 8 lines for entry? are you nuts?
mov ebx,eax ; copy
shr eax,1 ; divide by two
mov edi,offset ENTRY_ROW
mov ecx,ENTRIES
add eax,8 ; add one interline
mov dword ptr edi [edi],0 ; title position
add edi,4
row_row:
stosd
add eax,ebx
dec ecx
jne row_row
mov eax,200
pop esi ; restore pixel-lines of text in menu bottom
sub eax,esi
mov [edi],eax ; end text position
; menu data setup complete
freshen: ; refresh displayed data
mov esi,DARK6_TEXT+(DARK6_TEXT shl 8)+(DARK6_TEXT shl 16)+(DARK6_TEXT shl 24)
mov eax,_VDispX
mov ecx,40*2
mov edi,_ScrBase
mov ebx,25*8
mov edx,_VDispY
call _Block ; set background color
; NOW WRITE ENTRIES
mov edx,ENTRIES
mov esi,offset ENTRY_DATA
xor eax,eax
xor ecx,ecx
add edx,2 ; header & end
showall:
mov ebx,[esi]
add esi,4
mov al,[ebx] ; get menu entry type
pushad
call dword ptr [eax*4+SHOW]
popad
inc ecx
dec edx
jne showall
xor eax,eax
xor edx,edx
mov ecx,40*2
mov ebx,25*8
call _TouchBlock
call _PageFlip1
; and now go for menu animation
popad
ret
il_cursore db POINT0,POINT1,0
entry_refresh:
pushad
xor eax,eax
mov ebx,8
mov edx,[ecx*4+ENTRY_ROW]
mov ecx,40*2
call _TouchBlock ; refresh the current entry
mov eax,_VDispX
add edx,_VDispY
mov ebx,offset il_cursore
mov edi,_ScrBase
call _PutString ; write cursor
call _PageFlip1
popad
ret
public _PopMenu
_PopMenu:; eax = pointer to menu data
push _CHRFNT
pushad
; use the "not-input" character set
INPUT_OFF
call m_refresh ; refresh/generate the menu data from the description
mov ecx,1 ; cursor position on first entry
wazoom: call entry_refresh
call _WaitKey
wazaam:
xor ebx,ebx
mov edx,[ecx*4+ENTRY_DATA]
mov bl,[edx] ; get entry type
cmp byte ptr [eax+_ESC],KPRESSED ; WAIT FOR KEY PRESS&RELEASE
setnz [eax+_ESC]
je thee_eend
cmp byte ptr [eax+_LEFT],KPRESSED
setnz [eax+_LEFT]
je decc
cmp byte ptr [eax+_KMINUS],KPRESSED
setnz [eax+_KMINUS]
jne nodec
decc:
call [ebx*4+DECREMENT]
jmp wazoom
nodec:
cmp byte ptr [eax+_RIGHT],KPRESSED
setnz [eax+_RIGHT]
je incc
cmp byte ptr [eax+_KPLUS],KPRESSED
setnz [eax+_KPLUS]
jne noinc
incc:
call [ebx*4+INCREMENT]
jmp wazoom
noinc: cmp byte ptr [eax+_UP],KPRESSED
setnz [eax+_UP]
jne noo_uup
call [ebx*4+UPP]
jmp wazoom
noo_uup:cmp byte ptr [eax+_DOWN],KPRESSED
setnz [eax+_DOWN]
jne noo_dnn
call [ebx*4+DDN]
jmp wazoom
noo_dnn:cmp byte ptr [eax+_ENTER],KPRESSED
setnz [eax+_ENTER]
jne wazoom
call [ebx*4+SELECT]
test touchngo,01
jz notouchngo
call xsel ; trigger menu exit if this is a touch&go menu
notouchngo:
call entry_refresh
rescan:
call _WaitKey
test byte ptr [eax+_ENTER],KPRESSED ; do this
mov byte ptr [eax+_ENTER],0 ;
jnz rescan ; to avoid key "bounces"
jmp wazaam
thee_eend:
popad
pop _CHRFNT
ret
; Look into 386menu.txt for more info.
; This function lets you pop-up and "animate" a menu you defined.
; you can select and manipolate menu entry data
; using the keyboard
;
; up/down = change entry
; enter = enter a value from the keyboard / trigger entry
; (you can do this only one, then you must use another key
; before you can "select" the entry again
; this is because of the "debouncing" routine)
; left,'-' = decrease entry's value
; right,'+' = increase entry's value
; esc = quit menu (only if menu definition data allows it)
;
; N.B. It supposed that the calling routine will choose the best method
; to save the current screen context before performing the call
; and then it will refresh it on return.
code32 ends
end